library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;


entity udp_to_fifo is
port (
    --// clk, reset
    rst_n_i       : in std_logic;
    clk_sys_i     : in std_logic;
    udp_rx_data   : in std_logic_vector(15 downto 0);
        -- udp data field when udp_rx_data_valid = '1'
    udp_rx_data_valid: in std_logic;
        -- delineates the udp data field
    udp_rx_sof    : in std_logic;
        -- 1 clk pulse indicating that udp_rx_data is the first byte in the udp data field.
    udp_rx_eof    : in std_logic;
        -- 1 clk pulse indicating that udp_rx_data is the last byte in the udp data field.
        -- always check udp_rx_data_valid at the end of packet (udp_rx_eof = '1') to confirm
        -- that the udp packet is valid. external buffer may have to backtrack to the the last
        -- valid pointer to discard an invalid udp packet.
        -- reason: we only knows about bad udp packets at the end.
    fifo_wrdata   : out std_logic_vector(15 downto 0);  -- fifo dout
    fifo_wrclk    : out std_logic;
    fifo_wren     : out std_logic;
    fifo_full     : in  std_logic;
    fifo_prog_full: in  std_logic
);
end entity;

architecture rtl of udp_to_fifo is

  signal data: std_logic_vector(15 downto 0);
  signal wren: std_logic;
  signal fifo_prog_full_latch:std_logic;

begin

fifo_wrclk <= clk_sys_i;
fifo_wrdata<= data;
fifo_wren  <= wren;

p_latch_prog_full:process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
    if rst_n_i = '0' then
        fifo_prog_full_latch <= '0';        
    else
        if udp_rx_eof = '1' then
            fifo_prog_full_latch <= fifo_prog_full;
        end if;
    end if;
end if;
end process;

p_data : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
    if rst_n_i = '0' then
        data <= (others=>'0');
        wren <= '0';
    else
        wren <= (not fifo_prog_full_latch) and udp_rx_data_valid;
        data <= udp_rx_data;
    end if;
end if;
end process;

end architecture;
